cmake_minimum_required(VERSION 3.20)
## 定义是否启用 CUDA
option(my_USE_CUDA "Enable CUDA support" ON)
set(my_LANG_LIST)
if(my_USE_CUDA)
    set(my_LANG_LIST CUDA)
    # message(STATUS "[my] CMAKE_CUDA_COMPILER_FORCED -> TRUE")
    # set(CMAKE_CUDA_COMPILER "C:/MyProgram/cuda/bin/nvcc.exe")
    # set(CMAKE_CUDA_COMPILER_FORCED TRUE)
endif()
project(dose_torch LANGUAGES CXX ${my_LANG_LIST})
include(0configs.cmake)


##0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 python pyd module
set(my_LIB ${PROJECT_NAME})
# 设置自定义算子库
Python_add_library(${my_LIB} MODULE
    USE_SABI 3.9
    ## WITH_SOABI
    csrc/DoseStatTorch.cpp
)
my_config_msvc_relwithdebinfo(${my_LIB})
my_config_export_header(${my_LIB} ${my_EXPORTS_DIR} FALSE)

## 添加 public 头文件
target_sources(${my_LIB}
    PUBLIC FILE_SET HEADERS TYPE HEADERS
    BASE_DIRS
        "${CMAKE_CURRENT_SOURCE_DIR}/csrc" "${my_EXPORTS_DIR}"
    FILES
        csrc/DoseStatTorch.h
)

# 设置编译选项
target_compile_definitions(${my_LIB}
    PRIVATE
        TORCH_EXTENSION_NAME=${my_LIB}
)

# 链接PyTorch库
target_link_libraries(${my_LIB}
    PUBLIC torch
    #PRIVATE Python::Python
)

# 设置包含目录
target_include_directories(${my_LIB}
    PUBLIC
        ${TORCH_INCLUDE_DIRS}
        ${CMAKE_CURRENT_SOURCE_DIR}
)

##================================================================================= build time copy

##================================================================================= install time copy
##-----------------------------  python 模块目录
set(my_PY_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/src/dose_torch")
set(my_INST_PYD_DIR "${my_PY_ROOT}/lib")
set(my_INST_INC_DIR "${my_PY_ROOT}/include")

##----------------------------- 打包系统库
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)   # Win10 以前必备; 安装 Windows 通用 CRT（UCRT）库
set(CMAKE_INSTALL_DEBUG_LIBRARIES FALSE) # Debug 版 runtime
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)  # 禁止自动 install, 可以手动定制
include(InstallRequiredSystemLibraries)
message(STATUS "[my] System runtime detected:")
if(FALSE)
    foreach(f ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
        message("    ${f}")
    endforeach()
endif()

##----------------------------- 设置安装目录
install(TARGETS ${my_LIB}
    FILE_SET HEADERS DESTINATION "${my_INST_INC_DIR}"
    RUNTIME DESTINATION "${my_INST_PYD_DIR}"
    LIBRARY DESTINATION "${my_INST_PYD_DIR}"
    ARCHIVE DESTINATION "${my_INST_PYD_DIR}"
)

##----------------------------- windows, 打包 c10, c10_cuda, torch_cpu, torch_cuda 等 dll
if(FALSE AND WIN32)
    install(FILES "$<TARGET_RUNTIME_DLLS:${my_LIB}>"
        DESTINATION "${my_INST_PYD_DIR}"
    )
endif()

##----------------------------- conan runtime dlls
if(FALSE AND WIN32 AND EXISTS "${my_CONAN_RUNTIME_DIR}")
    install(DIRECTORY "${my_CONAN_RUNTIME_DIR}/" # 注意 trailing / 表示拷贝内容, 不带目录壳
        DESTINATION "${my_INST_PYD_DIR}"
        USE_SOURCE_PERMISSIONS
        ## 单独组件名, 可以使用 cmake --install . --component conan_runtime 单独装
        # COMPONENT conan_runtime
    )
endif()


##0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 c++ test dose_statistics lib
set(my_LIB2 dose_torch_dll)
# 设置自定义算子库
Python_add_library(${my_LIB2} SHARED
    csrc/DoseStatTorch.cpp
)
my_config_msvc_relwithdebinfo(${my_LIB2})

## 添加 public 头文件
target_sources(${my_LIB2}
    PUBLIC FILE_SET HEADERS TYPE HEADERS
    BASE_DIRS
        "${CMAKE_CURRENT_SOURCE_DIR}/csrc" "${my_EXPORTS_DIR}"
    FILES
        csrc/DoseStatTorch.h
)
# 设置编译选项
target_compile_definitions(${my_LIB2}
    PRIVATE
        TORCH_EXTENSION_NAME=${my_LIB2}
)

# 链接PyTorch库
target_link_libraries(${my_LIB2}
    PUBLIC torch
)

# 设置包含目录
target_include_directories(${my_LIB2}
    PUBLIC
        ${TORCH_INCLUDE_DIRS}
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${Python_INCLUDE_DIRS}
)

##====================================== find dependencies
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(cnpy CONFIG REQUIRED)

##====================================== add executable
set(my_EXE test_dose_torch)
add_executable(${my_EXE}
    csrc/TestDoseStatTorch.cpp
)

target_include_directories(${my_LIB2}
    PRIVATE
    ${Python_INCLUDE_DIRS}
)
# 链接依赖库
target_link_libraries(${my_EXE}
    PRIVATE
        fmt::fmt
        spdlog::spdlog $<$<BOOL:${MINGW}>:ws2_32>
        cnpy::cnpy
        ${my_LIB2}
        ${Python_LIBRARIES}
)
## 设置编译选项
target_compile_definitions(${my_EXE}
    PRIVATE
        MY_TESTIO_DIR="${my_TESTIO_DIR}"
        MY_TESTIO_CASE1="${my_TESTIO_DIR}/d250905_voxel_volume_dose.npz"
)


##================================================================================= build time copy
##----------------------------- copy conan file
if(TRUE AND WIN32 AND EXISTS "${my_CONAN_RUNTIME_DIR}")
    set(runtime_SOURCE_DIR "${my_CONAN_RUNTIME_DIR}")
    set(runtime_DEST_DIR "${my_PATH_BIN}/$<CONFIG>")
    # 添加自定义命令，在构建后拷贝文件
    add_custom_command(
        TARGET ${my_EXE} POST_BUILD
        # COMMAND ${CMAKE_COMMAND} -E make_directory "${RUNTIME_DEST_DIR}"
        COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different
            "${runtime_SOURCE_DIR}"
            "${runtime_DEST_DIR}"
        COMMENT "Copy runtime dlls, ${runtime_SOURCE_DIR} -> ${runtime_DEST_DIR}"
        VERBATIM
    )
endif()

##----------------------------- windows copy denpendencies
if(TRUE AND WIN32)
    add_custom_command(TARGET ${my_EXE} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:${my_EXE}> "${my_PATH_BIN}/$<CONFIG>"
        COMMAND_EXPAND_LISTS
        COMMENT "Copying DLLs to build directory")
endif()

##================================================================================= install time copy
if(TRUE AND WIN32)
    install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/runtime/"
        DESTINATION bin
        USE_SOURCE_PERMISSIONS
        ## 单独组件名, 可以使用 cmake --install . --component conan_runtime 单独装
        # COMPONENT conan_runtime
    )
endif()